﻿Imports System.Data.Common

Public Class GISMap
    Inherits System.Web.UI.Page

    'there are the range of plotted point sizes in points
    Shared MINSIZE As Double = 4.0
    Shared MAXSIZE As Double = 28.0

    Private Class clsMapSettings
        Friend dictMaps As New Dictionary(Of String, String)
        Friend MapSourceIndex As String = 0
        Friend MapTypeIndex As Integer = 0
        Friend PCode As String = ""
        Friend Sub Save()
            HttpContext.Current.Session("MapSettings") = Me
        End Sub
    End Class

    Private MapSettings As clsMapSettings

    Protected Overrides Sub InitializeCulture()
        With ProjectSettings
            System.Threading.Thread.CurrentThread.CurrentUICulture = .Language
            System.Threading.Thread.CurrentThread.CurrentCulture = .Language
        End With

        MyBase.InitializeCulture()
    End Sub

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        'retrieve previous settings
        MapSettings = Session("MapSettings")
        If MapSettings Is Nothing Then MapSettings = New clsMapSettings

        If Not IsPostBack Then
            With MapSettings
                lblInfo.Text = String.Format(GetLocalResourceObject("lblInfoResource1.Text"), NumSelectedRecords)
                FillMapList()
                FillPCodeList()
                cboMapSource.SelectedIndex = .MapSourceIndex
                hdnMapURL.Value = .dictMaps(cboMapSource.Text)
                cboMapType.SelectedIndex = .MapTypeIndex
                If .PCode <> "" Then cboPCode.Text = .PCode
            End With
        Else
            Session("dummy") = "dummy"
            'see if want to show graph form
            'Dim StationID As String = hdnStationID.Value
            'Dim PCode As String = hdnPCode.Value
            'If Not String.IsNullOrEmpty(StationID) And Not String.IsNullOrEmpty(PCode) Then
            '    With ProjectSettings
            '        .GraphStation = StationID
            '        .GraphPCode = PCode
            '        .Save()
            '    End With
            '    'HttpContext.Current.Response.Redirect("Graph.aspx")
            '    Server.Transfer("Graph.aspx")
            'End If
        End If

        lblPCode.Style("Display") = IIf(cboMapType.Text.Contains("Locations"), "none", "normal")
        cboPCode.Style("Display") = IIf(cboMapType.Text.Contains("Locations"), "none", "normal")
        Dim p As Object = Context.Session("Project")

    End Sub

    ''' <summary>
    ''' Load map names and URLs from text file and fill dictionary and dropdownlist
    ''' </summary>
    Private Sub FillMapList()
        If MapSettings Is Nothing Then Response.Redirect("Configure.aspx") 'if session terminates or website restarts; goto configure screen
        With MapSettings
            cboMapSource.Items.Clear()
            .dictMaps.Clear()
            Dim sr As New IO.StreamReader(MapPath("~\Maps\Maps.txt"))
            sr.ReadLine() 'skip first line of comments
            While Not sr.EndOfStream
                Dim ar() As String = sr.ReadLine.Split(vbTab)
                If ar.Length = 2 Then
                    If Not .dictMaps.ContainsKey(ar(0)) Then
                        .dictMaps.Add(ar(0), ar(1))
                        cboMapSource.Items.Add(ar(0))
                    End If
                End If
            End While
            sr.Close()
            If cboMapSource.Items.Count > 0 Then cboMapSource.SelectedIndex = 0
            hdnMapURL.Value = .dictMaps(cboMapSource.Text)
            .Save()
        End With
    End Sub

    Private Sub FillPCodeList()
        CheckSelectedData()
        'return list of distinct pcodes so can fill combobox
        Dim dt As DataTable = SelectedDataTable
        If dt Is Nothing Then Exit Sub
        dt.DefaultView.Sort = "PCode"
        dt.DefaultView.RowFilter = ""
        cboPCode.Items.Clear()
        Dim dtPCodes As DataTable = dt.DefaultView.ToTable(True, {"PCode"})
        For Each dr As DataRow In dtPCodes.Rows
            If Not IsDBNull(dr(0)) Then
                'add PCode - AnalName to list
                Dim PCode As String = dr(0)
                Dim datarowsAnal() As DataRow = ProjectDataset.Tables("PCodes").Select(String.Format("PCode = '{0}'", PCode), "PCode")
                Dim AnalName As String = "Unknown"
                If datarowsAnal.Length = 1 Then
                    AnalName = TestNull(datarowsAnal(0)("Anal_Name"), "")
                End If
                cboPCode.Items.Add(PCode & " - " & AnalName)
            End If
        Next
    End Sub

    Private Sub cboMapType_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboMapType.SelectedIndexChanged
        If cboMapType.SelectedIndex = 3 Then
            lblPCode.Style("Display") = "none"
            cboPCode.Style("Display") = "none"
        Else
            lblPCode.Style("Display") = "normal"
            cboPCode.Style("Display") = "normal"
        End If
        If MapSettings Is Nothing Then Response.Redirect("Configure.aspx") 'if session terminates or website restarts; goto configure screen
        With MapSettings
            .MapTypeIndex = cboMapType.SelectedIndex
            .Save()
        End With
    End Sub

    Private Sub cboMapSource_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboMapSource.SelectedIndexChanged
        If MapSettings Is Nothing OrElse Not MapSettings.dictMaps.ContainsKey(cboMapSource.Text) Then Response.Redirect("Configure.aspx") 'if session terminates or website restarts; goto configure screen
        With MapSettings
            Dim URL As String = .dictMaps(cboMapSource.Text)
            Dim testURL As String = ""
            If URL.ToUpper.StartsWith("HTTP:") Or URL.ToUpper.StartsWith("HTTPS:") Then testURL = URL
            If Not IsConnectionAvailable(testURL) Then
                RegisterScript(UpdatePanel1, "MapLoadError();")
                'Server.Transfer("Map.aspx")
                Exit Sub
            End If
            hdnMapURL.Value = URL
            .MapSourceIndex = cboMapSource.SelectedIndex
            .Save()
        End With
    End Sub

    Private Sub cboPCode_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboPCode.SelectedIndexChanged
        If MapSettings Is Nothing Then Response.Redirect("Configure.aspx") 'if session terminates or website restarts; goto configure screen
        With MapSettings
            .PCode = cboPCode.Text
            .Save()
        End With
    End Sub

    ''' <summary>
    ''' This PageMethod allows a resource value to be passed to the page so JavaScript can display message in correct language
    ''' </summary>
    <System.Web.Services.WebMethod()>
    Public Shared Function GetResource(key As String) As String
        Dim res As String = HttpContext.GetGlobalResourceObject("WRDB", key, ProjectSettings.Language)
        If String.IsNullOrEmpty(res) Then Throw New ApplicationException("Resource was not found: " & key) Else Return res
    End Function

    <System.Web.Services.WebMethod()>
    Public Shared Function GetMapURL(MapName As String) As Object
        Dim MapSettings As clsMapSettings = HttpContext.Current.Session("MapSettings")
        If MapSettings.dictMaps.ContainsKey(MapName) Then
            Return MapSettings.dictMaps(MapName)
        Else
            Return Nothing
        End If
    End Function

    <System.Web.Services.WebMethod()>
    Public Shared Function GetStations(MapType As String, PCode As String) As Object

        'change so is displaying selected data...

        'connect to database if necessary
        If Not ProjectSettings.Load Then Return Nothing

        Dim dtSta As DataTable = Nothing

        'retrieve stations from support table
        Project.DB.AddTable(dtSta, "SELECT Station_ID, Station_Name, Latitude, Longitude, Station_Type, 10.0 AS Size FROM Stations WHERE Latitude IS NOT NULL AND Longitude IS NOT NULL AND Latitude <> 0.0 AND Longitude <> 0.0")

        If MapType.Contains("Station Locations") Then

            'will just pass back stations just queried

        Else

            'retrieve previously selected data
            Dim dt As DataTable = SelectedDataTable.Copy
            If SelectedDataTable Is Nothing Then Return Nothing

            'note: caller will pass contents of combobox as PCode which now contains PCode - AnalName----parse it
            PCode = StringSplit(PCode, " - ")(0)

            'determine desired size of each symbol by retrieving min and max value
            Dim MinResult As Object = dt.Compute("MIN(Result)", String.Format("PCode='{0}'", PCode))
            Dim MaxResult As Object = dt.Compute("MAX(Result)", String.Format("PCode='{0}'", PCode))

            'create new resultset by linking query result with Stations table

            '1. select only pcode and sort
            dt.DefaultView.RowFilter = String.Format("PCode='{0}'", PCode)
            dt.DefaultView.Sort = "Station_ID"

            '2. get distinct set of selected stations
            Dim dtDta As DataTable = dt.DefaultView.ToTable(True, {"Station_ID"})

            '3. add additional columns so the format is the same for javascript; add additional columns if displaying data values
            With dtDta.Columns
                .Add("Station_Name", GetType(String))
                .Add("Latitude", GetType(Double))
                .Add("Longitude", GetType(Double))
                .Add("Station_Type", GetType(String))
                .Add("Size", GetType(Double))
                .Add("Count", GetType(String))
                .Add("MinResult", GetType(String))
                .Add("MaxResult", GetType(String))
                .Add("AvgResult", GetType(String))
                .Add("MinDate", GetType(String))
                .Add("MaxDate", GetType(String))
                .Add("Result", GetType(String))
            End With

            '4. fill in the blanks
            For Each dr As DataRow In dtDta.Rows
                Dim arRows = dtSta.Select(String.Format("Station_ID='{0}'", dr("Station_ID")))
                If arRows.Length <> 0 Then
                    dr("Station_Name") = arRows(0)("Station_Name")
                    dr("Latitude") = arRows(0)("Latitude")
                    dr("Longitude") = arRows(0)("Longitude")
                    dr("Station_Type") = arRows(0)("Station_Type")

                    'determine min/max/avg result for this station from data table
                    Dim agg As String = ""
                    Select Case MapType
                        Case "Minimum Values" : agg = "MIN"
                        Case "Average Values" : agg = "AVG"
                        Case "Maximum Values" : agg = "MAX"
                        Case Else
                            Throw New ApplicationException("Invalid MapType")
                    End Select
                    Dim filter As String = String.Format("Station_ID='{0}' AND PCode='{1}'", dr("Station_ID"), PCode)
                    Dim res As Double = dt.Compute(agg & "(Result)", filter)
                    Dim size As Double = 1.0
                    If MinResult <> MaxResult Then
                        size = (res - MinResult) / (MaxResult - MinResult) * (MAXSIZE - MINSIZE) + MINSIZE
                    End If

                    dr("Size") = Math.Round(size, 1)
                    dr("Count") = CLng(dt.Compute("COUNT(Result)", filter)).ToString("N0")
                    dr("MinResult") = CDbl(dt.Compute("MIN(Result)", filter)).ToString("N3")
                    dr("MaxResult") = CDbl(dt.Compute("MAX(Result)", filter)).ToString("N3")
                    dr("AvgResult") = CDbl(dt.Compute("AVG(Result)", filter)).ToString("N3")
                    dr("MinDate") = CDate(dt.Compute("MIN(Date_Time)", filter)).ToString("d")
                    dr("MaxDate") = CDate(dt.Compute("MAX(Date_Time)", filter)).ToString("d")
                    dr("Result") = CDbl(dt.Compute(agg & "(Result)", filter)).ToString("N3") 'numeric value for desired statistic (for labeling)

                End If
            Next

            '5. overwrite datatable with the one I just built
            dtSta = dtDta

        End If

        'return results to JavaScript as a JSON object

        Dim rows As New List(Of Dictionary(Of String, Object))()
        Array.ForEach(dtSta.[Select](), Function(row)
                                            Dim Dictionary As New Dictionary(Of String, Object)()
                                            For Each col As DataColumn In dtSta.Columns
                                                Dictionary.Add(col.ColumnName, row(col))
                                            Next
                                            rows.Add(Dictionary)
                                            Return rows
                                        End Function)
        Return rows
    End Function

    '<System.Web.Services.WebMethod()>
    'Public Shared Sub ShowGraph(StationID As String, PCode As String)
    '    With ProjectSettings
    '        .GraphStation = StationID
    '        .GraphPCode = PCode
    '        .Save()
    '    End With
    '    Try
    '        HttpContext.Current.Response.Redirect("Graph.aspx", False)
    '    Catch ex As Threading.ThreadAbortException
    '        'this is expected
    '    Catch ex As Exception
    '        Throw
    '    End Try
    'End Sub

    'Private Sub btnHidden_Click(sender As Object, e As EventArgs) Handles btnHidden.Click
    '    Dim p As Object = Context.Session("Project")
    '    HttpContext.Current.Response.Redirect("Graph.aspx")
    'End Sub


    'note I tried a long time to get button from infowindow to redirect to graph page but was unsuccessful
    'something about clicking the button on the map page caused the session variable to get reset and I could find no workaround

    Private Sub btnHidden_Click(sender As Object, e As EventArgs) Handles btnHidden.Click
        Dim StationID As String = hdnStationID.Value
        Dim PCode As String = hdnPCode.Value
        If Not String.IsNullOrEmpty(StationID) And Not String.IsNullOrEmpty(PCode) Then
            With ProjectSettings
                .GraphStation = StationID
                .GraphPCode = PCode
                .Save()
            End With
            Response.Redirect("Graph.aspx", False)
            'Server.Transfer("Graph.aspx")
        End If
    End Sub

    Public Function IsConnectionAvailable(URL As String) As Boolean

        'note: I had good intentions, but now realize that this is testing whether the SERVER has a connection to the Internet, not the client
        'For now, always return True and if there is no connection, it will soon become obvious

        If URL = "" Then Return True ' URL = "http://www.arcgis.com" 'if pass name of generic map instead of URL

        ' Returns True if connection to specified URL is available 
        Dim objUrl As New System.Uri(URL)
        ' Setup WebRequest
        Dim objWebReq As System.Net.WebRequest
        objWebReq = System.Net.WebRequest.Create(objUrl)
        Dim objResp As System.Net.WebResponse = Nothing
        Try
            ' Attempt to get response and return True
            objResp = objWebReq.GetResponse
            objResp.Close()
            objWebReq = Nothing
            Return True
        Catch ex As Exception
            ' Error, exit and return False
            If objResp IsNot Nothing Then objResp.Close()
            objWebReq = Nothing
            Return False
        End Try
    End Function

End Class